#include "FitCurveTool.h"
#include "Ent.h"

bool lengthApprox2(double l1, double l2)
{
	return std::abs(l1 - l2) < 0.001; // 1mm
}

bool constructPointCurvesMap(const std::vector<CurvePoints>& curves,
	std::map<osg::Vec3d, TwoConnectedCurves, LessVec3f2>& result, bool& open, osg::Vec3d& begin, osg::Vec3d& end)
{
	for (const auto& e : curves)
	{
		auto point = e.points.front();
		auto it = result.find(point);
		if (it == result.end())
		{
			result.insert({ point, { e.curve, e.points, true } });
		}
		else
		{
			if (it->second.m_curve2.curve)
			{
				// 一个点有三条线，不合法
				return false;
			}
			it->second.m_curve2 = { e.curve, e.points, true };
		}

		point = e.points.back();
		it = result.find(point);
		if (it == result.end())
		{
			result.insert({ point, { e.curve, e.points, false } });
		}
		else
		{
			if (it->second.m_curve2.curve)
			{
				// 一个点有三条线，不合法
				return false;
			}
			it->second.m_curve2 = { e.curve, e.points, false };
		}
	}
	// 点连接一条线的计数
	int countOf1Cuve = 0;
	for (const auto& e : result)
	{
		if (!e.second.m_curve2.curve)
		{
			++countOf1Cuve;
			if (countOf1Cuve == 1)
			{
				begin = e.first;
			}
			else if (countOf1Cuve == 2)
			{
				end = e.first;
			}
		}
	}
	open = countOf1Cuve == 2;
	return result.size() >= 3 && (countOf1Cuve == 0 /*封闭*/ || countOf1Cuve == 2/*开放*/);
}

// 这是递归函数
void connectCurve(const std::map<osg::Vec3d, TwoConnectedCurves, LessVec3f2>& ptToTwoCurveEndPointMap,
	std::set<std::shared_ptr<Ent>>& usedEnts,
	std::vector<osg::Vec3d>& result)
{
	auto pt = result.back();
	auto it = ptToTwoCurveEndPointMap.find(pt);
	if (it != ptToTwoCurveEndPointMap.end())
	{
		// curve1 is not used
		if (usedEnts.find(it->second.m_curve1.curve) == usedEnts.end())
		{
			if (it->second.m_curve1.isFirst)
			{
				// 顺序加入除第一点外的其他点
				for (int i = 1; i < it->second.m_curve1.points.size(); ++i)
					result.push_back(it->second.m_curve1.points[i]);
			}
			else
			{
				// 逆序加入除最后一点外的其他点
				for (int i = it->second.m_curve1.points.size() - 2; i >= 0; --i)
					result.push_back(it->second.m_curve1.points[i]);
			}
			usedEnts.insert(it->second.m_curve1.curve);
			connectCurve(ptToTwoCurveEndPointMap, usedEnts, result);
		}
		// curve2 is not used
		else if (it->second.m_curve2.curve && usedEnts.find(it->second.m_curve2.curve) == usedEnts.end())
		{
			if (it->second.m_curve2.isFirst)
			{
				// 顺序加入除第一点外的其他点
				for (int i = 1; i < it->second.m_curve2.points.size(); ++i)
					result.push_back(it->second.m_curve2.points[i]);
			}
			else
			{
				// 逆序加入除最后一点外的其他点
				for (int i = it->second.m_curve2.points.size() - 2; i >= 0; --i)
					result.push_back(it->second.m_curve2.points[i]);
			}
			usedEnts.insert(it->second.m_curve2.curve);
			connectCurve(ptToTwoCurveEndPointMap, usedEnts, result);
		}
	}
}

std::vector<osg::Vec3d> connectEnds(const std::vector<CurvePoints>& endPoints,
	std::set<std::shared_ptr<Ent>>& usedEnts)
{
	std::map<osg::Vec3d, TwoConnectedCurves, LessVec3f2> ptToTwoCurveEndPointMap;
	bool open;
	osg::Vec3d begin, end;
	bool success = constructPointCurvesMap(endPoints, ptToTwoCurveEndPointMap, open, begin, end);
	std::vector<osg::Vec3d> result;
	if (!success)
		return result;
	if (open)
	{
		result.push_back(begin);
		connectCurve(ptToTwoCurveEndPointMap, usedEnts, result);
	}
	else
	{
		const auto& e = *ptToTwoCurveEndPointMap.begin();
		result.push_back(e.first);
		connectCurve(ptToTwoCurveEndPointMap, usedEnts, result);
	}
	return result;
}
